﻿using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace GenUI.WPF.GenControls
{
    public class CircleProgress : Control
    {
        EllipseGeometry ellin;
        EllipseGeometry ellout;
        TextBlock tb;
        Path pathout;
        Path path;

        private double _maxValue = 100;
        public double MaxValue
        {
            get { return _maxValue; }
            set
            {
                _maxValue = value;
                Refresh(this);
            }
        }

        private double _minValue = 0;
        public double MinValue
        {
            get { return _minValue; }
            set
            {
                _minValue = value;
                Refresh(this);
            }
        }

        private static void OnProppertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is CircleProgress cp)
            {
                cp.Refresh();
            }
        }

        public double MaxRadius
        {
            get => (double)GetValue(MaxRadiusProperty);
            set => SetValue(MaxRadiusProperty, value);
        }

        public static readonly DependencyProperty MaxRadiusProperty =
               DependencyProperty.Register("MaxRadius", typeof(double), typeof(CircleProgress), new PropertyMetadata(OnProppertyChanged));


        public double MinRadius
        {
            get => (double)GetValue(MinRadiusProperty);
            set => SetValue(MinRadiusProperty, value);
        }

        public static readonly DependencyProperty MinRadiusProperty =
               DependencyProperty.Register("MinRadius", typeof(double), typeof(CircleProgress), new PropertyMetadata( OnProppertyChanged));

        public double Value
        {
            get => (double)GetValue(ValueProperty);
            set => SetValue(ValueProperty, value);
        }

        public static readonly DependencyProperty ValueProperty =
               DependencyProperty.Register("Value", typeof(double), typeof(CircleProgress), new PropertyMetadata(OnValueXChanged));

        private static void OnValueXChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is CircleProgress cp)
            {
                double ov = (double)e.OldValue;
                double nv = (double)e.NewValue;
                if (nv > cp.MaxValue) nv = cp.MaxValue;
                if (nv < cp.MinValue) nv = cp.MinValue;
                if (ov > cp.MaxValue) ov = cp.MaxValue;
                if (ov < cp.MinValue) ov = cp.MinValue;

                DoubleAnimation animation = new DoubleAnimation(ov, nv, new Duration(TimeSpan.FromMilliseconds(1000)));
                cp.BeginAnimation(ValueCopyProperty, animation);
                cp.ValueCopy = nv;
            }
        }
        private double ValueCopy
        {
            get => (double)GetValue(ValueCopyProperty);
            set => SetValue(ValueCopyProperty, value);
        }

        private static readonly DependencyProperty ValueCopyProperty =
               DependencyProperty.Register("ValueCopy", typeof(double), typeof(CircleProgress), new PropertyMetadata(OnPropertyChanged));

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is CircleProgress cp)
            {
                cp.Refresh();
            }
        }

        static CircleProgress()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CircleProgress), new FrameworkPropertyMetadata(typeof(CircleProgress)));
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            ellout = GetTemplateChild("PART_ellout") as EllipseGeometry;
            ellin = GetTemplateChild("PART_ellin") as EllipseGeometry;
            tb = GetTemplateChild("PART_tb") as TextBlock;
            pathout = GetTemplateChild("PART_pathout") as Path;
            path = GetTemplateChild("PART_path") as Path;
            Refresh();
        }
        private void Refresh(CircleProgress cp = null)
        {
            if (ellout != null && ellin != null)
            {
                ellout.RadiusX = MaxRadius;
                ellout.RadiusY = MaxRadius;

                ellin.RadiusX = MinRadius;
                ellin.RadiusY = MinRadius;
            }
            int 大小弧 = ValueCopy > ((MaxValue - MinValue) / 2) ? 1 : 0;
            double 旋转角度 = (ValueCopy / (MaxValue - MinValue)) * 360;

            double X1 = -((MaxRadius + MinRadius) / 2) * Math.Sin((旋转角度 / 180) * Math.PI);
            double Y1 = ((MaxRadius + MinRadius) / 2) * Math.Cos((旋转角度 / 180) * Math.PI);
            if (path != null)
            {
                if (ValueCopy == MaxValue)
                {
                    pathout.Fill = path.Stroke;
                }
                else
                {
                    BrushConverter brushConverter = new BrushConverter();
                    pathout.Fill = (Brush)brushConverter.ConvertFromString("#99b7d2");
                }
                tb.Text = $"{(ValueCopy - MinValue) / (MaxValue - MinValue) * 100:0.00}%";
                string sData = $"M0,{(MaxRadius + MinRadius) / 2} A{(MaxRadius + MinRadius) / 2},{(MaxRadius + MinRadius) / 2} 0 {大小弧} 1 {X1},{Y1}";
                var convert = TypeDescriptor.GetConverter(typeof(Geometry));
                this.path.StrokeThickness = MaxRadius - MinRadius;
                this.path.Data = (Geometry)convert.ConvertFromString(sData);
            }
        }
    }
}
